///
///	@file bdf2c.c		@brief BDF Font to C source convertor
///
///	Copyright (c) 2009, 2010 by Lutz Sammer.  All Rights Reserved.
///
///	Contributor(s):
///
///	License: AGPLv3
///
///	This program is free software: you can redistribute it and/or modify
///	it under the terms of the GNU Affero General Public License as
///	published by the Free Software Foundation, either version 3 of the
///	License.
///
///	This program is distributed in the hope that it will be useful,
///	but WITHOUT ANY WARRANTY; without even the implied warranty of
///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
///	GNU Affero General Public License for more details.
///
///	$Id: 2543638c3dbafb66df95f4534e42c596a9749e90 $
//////////////////////////////////////////////////////////////////////////////

///
///	@mainpage
///		bdf2c - converts bdf font files into C include files.
///
///		The Bitmap Distribution Format (BDF) is a file format for
///		storing bitmap fonts. The content is presented as a text file
///		that is intended to be human and computer readable.
///
///	BDF input:
///	@code
///	STARTCHAR A
///	ENCODING 65
///	SWIDTH 568 0
///	DWIDTH 8 0
///	BBX 8 13 0 -2
///	BITMAP
///	00
///	38
///	7C
///	C6
///	C6
///	C6
///	FE
///	C6
///	C6
///	C6
///	C6
///	00
///	00
///	ENDCHAR
///	@endcode
///
///	The result looks like this:
///	@code
///	//	65 $41 'A'
///	//	width 8, bbx 0, bby -2, bbw 8, bbh 13
///		________,
///		__XXX___,
///		_XXXXX__,
///		XX___XX_,
///		XX___XX_,
///		XX___XX_,
///		XXXXXXX_,
///		XX___XX_,
///		XX___XX_,
///		XX___XX_,
///		XX___XX_,
///		________,
///		________,
///	@endcode
///

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define VERSION "4"			///< version of this application

//////////////////////////////////////////////////////////////////////////////

int Outline;				///< true generate outlined font
int SmartMatrix;			// modify output to be used in the SmartMatrix library

//////////////////////////////////////////////////////////////////////////////

///
///	Create our header file.
///
///	@param out	file stream for output
///
void CreateFontHeaderFile(FILE * out)
{
	register int i;

	fprintf(out,
	"// (c) 2009, 2010 Lutz Sammer, License: AGPLv3\n\n"
	"\t/// bitmap font structure\n" "struct bitmap_font {\n"
	"\tunsigned char Width;\t\t///< max. character width\n"
	"\tunsigned char Height;\t\t///< character height\n"
	"\tunsigned short Chars;\t\t///< number of characters in font\n"
	"\tconst unsigned char *Widths;\t///< width of each character\n"
	"\tconst unsigned short *Index;\t///< encoding to character index\n"
	"\tconst unsigned char *Bitmap;\t///< bitmap of all characters\n"
	"};\n\n");

	fprintf(out, "\t/// @{ defines to have human readable font files\n");
	for (i = 0; i < 256; ++i) {
	fprintf(out, "#define %c%c%c%c%c%c%c%c 0x%02X\n",
		(i & 0x80) ? 'X' : '_', (i & 0x40) ? 'X' : '_',
		(i & 0x20) ? 'X' : '_', (i & 0x10) ? 'X' : '_',
		(i & 0x08) ? 'X' : '_', (i & 0x04) ? 'X' : '_',
		(i & 0x02) ? 'X' : '_', (i & 0x01) ? 'X' : '_', i);
	}
	fprintf(out, "\t/// @}\n");
}

//////////////////////////////////////////////////////////////////////////////

///
///	Print last data for c file.
///
///	@param out	file stream for output
///
void Last(FILE * out)
{
	fprintf(out, "// EOF\n");
	fprintf(out, "0,0,0,0,0,0,0,0,0\n");
}


///
///	Print header for c file.
///
///	@param out	file stream for output
///	@param name	font variable name in C source file
///
void Header(FILE * out, const char *name, int fontboundingbox_width, int fontboundingbox_height)
{
	char * headername;
	if(!SmartMatrix)
		headername = "font";
	else
		headername = "MatrixFontCommon";

#if 0
	fprintf(out,
	"// Created from bdf2c Version %s, (c) 2009, 2010 by Lutz Sammer\n"
	"//\tLicense AGPLv3: GNU Affero General Public License version 3\n"
	"\n#include \"%s.h\"\n\n", VERSION, headername);
#endif
	fprintf(out,
	"// Created from bdf2c Version %s, (c) 2009, 2010 by Lutz Sammer\n"
	"//\tLicense AGPLv3: GNU Affero General Public License version 3\n"
	,VERSION);

	fprintf(out,
	"// character bitmap for each encoding\n"
	"unsigned char __%s_bitmap__[] = {\n", name);

	fprintf(out,
	"// fontboundingbox_width\n"
	"%d,\n", fontboundingbox_width);

	fprintf(out,
	"// fontboundingbox_height\n"
	"%d,\n", fontboundingbox_height);
}

///
///	Print width table for c file
///
///	@param out		file stream for output
///	@param name		font variable name in C source file
///	@param width_table	width table read from BDF file
///	@param chars		number of characters in width table
///
void WidthTable(FILE * out, const char *name, const unsigned *width_table,
	int chars)
{
	fprintf(out, "};\n\n");

	fprintf(out,
	"\t/// character width for each encoding\n"
	"static const unsigned char __%s_widths__[] = {\n", name);
	while (chars--) {
	fprintf(out, "\t%u,\n", *width_table++);
	}
}

///
///	Print encoding table for c file
///
///	@param out		file stream for output
///	@param name		font variable name in C source file
///	@param encoding_table	encoding table read from BDF file
///	@param chars		number of characters in encoding table
///
void EncodingTable(FILE * out, const char *name,
	const unsigned *encoding_table, int chars)
{
	fprintf(out, "};\n\n");

	fprintf(out,
	"\t/// character encoding for each index entry\n"
	"static const unsigned short __%s_index__[] = {\n", name);
	while (chars--) {
	fprintf(out, "\t%u,\n", *encoding_table++);
	}
}

///
///	Print footer for c file.
///
///	@param out		file stream for output
///	@param name		font variable name in C source file
///	@param width		character width of font
///	@param height		character height of font
///	@param chars		number of characters in font
///
void Footer(FILE * out, const char *name, int width, int height, int chars)
{
	fprintf(out, "};\n\n");
	fprintf(out,
	"\t/// bitmap font structure\n" "const struct bitmap_font %s = {\n",
	name);
	fprintf(out, "\t.Width = %d, .Height = %d,\n", width, height);
	fprintf(out, "\t.Chars = %d,\n", chars);

	if(!SmartMatrix)
		fprintf(out, "\t.Widths = __%s_widths__,\n", name);
	else
		fprintf(out, "\t.Widths = 0,\n");

	fprintf(out, "\t.Index = __%s_index__,\n", name);
	fprintf(out, "\t.Bitmap = __%s_bitmap__,\n", name);
	fprintf(out, "};\n\n");
}

///
///	Dump character.
///
///
void DumpCharacter(FILE * out, unsigned char *bitmap, int fontwidth, int fontheight, int fontyoffset, int charheight, int charyoffset, int flag)
{
	int x;
	int y;
	int c;

	// how many rows from the top of the font bounding box is the top of this character?
	int yoffset = fontheight - charheight + (fontyoffset - charyoffset);

	if (flag == 1) {

	int y_start = 0;
	int y_end = 0;
	int num_data = 0;
	for (y = 0; y < fontheight; ++y) {
		for (x = 0; x < fontwidth; x += 8) {
			// if current row is above or below the bitmap, output a blank row
			if(y < yoffset || y > yoffset + charheight) {
				c = 0;
			} else {
				if (num_data == 0) y_start = y;
				y_end = y;
				num_data++;
				c = bitmap[(y - yoffset) * ((fontwidth + 7) / 8) + x / 8];
			}
		}
	}

	fprintf(out, "%d,%d,%d,", num_data, y_start, y_end);
	for (y = 0; y < fontheight; ++y) {
		for (x = 0; x < fontwidth; x += 8) {
			// if current row is above or below the bitmap, output a blank row
			if(y < yoffset || y > yoffset + charheight) {
				c = 0;
			} else {
				c = bitmap[(y - yoffset) * ((fontwidth + 7) / 8) + x / 8];
				fprintf(out, "0x%02x,", c);
			}
#if 0
			if (c & 0x80) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x40) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x20) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x10) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x08) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x04) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x02) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			if (c & 0x01) {
			fputc('X', out);
			} else {
			fputc('_', out);
			}
			fputc(',', out);
#endif
		} // end x
#if 0
		fputc('\n', out);
#endif
	} // end y
	fprintf(out, "\n");
	} // end flag

	if (flag == 2) {
	fputc('\n', out);
	for (y = 0; y < fontheight; ++y) {
		fputc('\t', out);
		for (x = 0; x < fontwidth; x += 8) {
			// if current row is above or below the bitmap, output a blank row
			if(y < yoffset || y > yoffset + charheight)
				c = 0;
			else
				c = bitmap[(y - yoffset) * ((fontwidth + 7) / 8) + x / 8];

			if (c & 0x80) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x40) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x20) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x10) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x08) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x04) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x02) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			if (c & 0x01) {
				fputc('X', out);
			} else {
				fputc('_', out);
			}
			fputc(',', out);
		} // end x
	fputc('\n', out);
	} // end y
	} // end flag

}

///
///	Hex ascii to integer
///
///	@param p	hex input character (0-9a-fA-F)
///
///	@returns converted integer
///
static inline int Hex2Int(const char *p)
{
	if (*p <= '9') {
	return *p - '0';
	} else if (*p <= 'F') {
	return *p - 'A' + 10;
	} else {
	return *p - 'a' + 10;
	}
}

///
///	Rotate bitmap.
///
///	@param bitmap	input bitmap
///	@param shift	rotate counter (0-7)
///	@param width	character width
///	@param height	character height
///
void RotateBitmap(unsigned char *bitmap, int shift, int width, int height)
{
	int x;
	int y;
	int c;
	int o;

	if (shift < 0 || shift > 7) {
		//fprintf(stderr, "This shift [%d] isn't supported\n", shift);
		//exit(-1);
		shift = 7;
	}

	if (shift != 0) {
		for (y = 0; y < height; ++y) {
			o = 0;
			for (x = 0; x < width; x += 8) {
				c = bitmap[y * ((width + 7) / 8) + x / 8];
				bitmap[y * ((width + 7) / 8) + x / 8] = c >> shift | o;
				o = c << (8 - shift);
			} // end x
		} // end y
	}
}

///
///	Outline character.	Create an outline font from normal fonts.
///
///	@param bitmap	input bitmap
///	@param width	character width
///	@param height	character height
///
void OutlineCharacter(unsigned char *bitmap, int width, int height)
{
	int x;
	int y;
	unsigned char *outline;

	outline = alloca(((width + 7) / 8) * height);
	memset(outline, 0, ((width + 7) / 8) * height);
	for (y = 0; y < height; ++y) {
	for (x = 0; x < width; ++x) {
		// Bit not set check surroundings
		if (~bitmap[y * ((width + 7) / 8) + x / 8] & (0x80 >> x % 8)) {
		// Upper row bit was set
		if (y
			&& bitmap[(y - 1) * ((width + 7) / 8) +
			x / 8] & (0x80 >> x % 8)) {
			outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
			// Previous bit was set
		} else if (x
			&& bitmap[y * ((width + 7) / 8) + (x -
				1) / 8] & (0x80 >> (x - 1) % 8)) {
			outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
			// Next bit was set
		} else if (x < width - 1
			&& bitmap[y * ((width + 7) / 8) + (x +
				1) / 8] & (0x80 >> (x + 1) % 8)) {
			outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
			// below row was set
		} else if (y < height - 1
			&& bitmap[(y + 1) * ((width + 7) / 8) +
			x / 8] & (0x80 >> x % 8)) {
			outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
		}
		}
	}
	}
	memcpy(bitmap, outline, ((width + 7) / 8) * height);
}

///
/// dump buffer
///
void dump(char * text, unsigned char *dt, int n)
{
	int clm = 0;
	unsigned char data;
	unsigned int saddr =0;
	unsigned int eaddr =n-1;

	printf("\n%s\n", text);
	//for (int i=0;i<16;i++) vsum[i]=0;  
	for (int addr = saddr; addr <= eaddr; addr++) {
		data = dt[addr];
		printf("%02x ",data);
		clm++;
		if (clm == 16) {
			printf("| \n");
			clm = 0;
		}
	}
}


///
///	Read BDF font file.
///
///	@param bdf	file stream for input (bdf file)
///	@param out	file stream for output (C source file)
///	@param name	font variable name in C source file
///
///	@todo bbx isn't used to correct character position in bitmap
///
void ReadBdf(FILE * bdf, FILE * out, const char *name, int flag)
{
	char linebuf[1024];
	char *s;
	char *p;
	int fontboundingbox_width;
	int fontboundingbox_height;
	int fontboundingbox_xoff;
	int fontboundingbox_yoff;
	int chars;
	int i;
	int j;
	int n;
	int scanline;
	char charname[1024];
	int encoding;
	int bbx;
	int bby;
	int bbw;
	int bbh;
	int width;
	int _bbx;
	int _width;
	unsigned *width_table;
	unsigned *encoding_table;
	unsigned char *bitmap;

	fontboundingbox_width = 0;
	fontboundingbox_height = 0;
	fontboundingbox_xoff = 0;
	fontboundingbox_yoff = 0;
	chars = 0;

	for (;;) {
		if (!fgets(linebuf, sizeof(linebuf), bdf)) {	// EOF
			break;
		}
		if (!(s = strtok(linebuf, " \t\n\r"))) {	// empty line
			break;
		}
		// printf("token:%s\n", s);
		if (!strcasecmp(s, "FONTBOUNDINGBOX")) {
			p = strtok(NULL, " \t\n\r");
			fontboundingbox_width = atoi(p);
			p = strtok(NULL, " \t\n\r");
			fontboundingbox_height = atoi(p);
			p = strtok(NULL, " \t\n\r");
			fontboundingbox_xoff = atoi(p);
			p = strtok(NULL, " \t\n\r");
			fontboundingbox_yoff = atoi(p);
		} else if (!strcasecmp(s, "CHARS")) {
			p = strtok(NULL, " \t\n\r");
			chars = atoi(p);
			break;
		}
	} // end for
	
#if 0
	printf("%d * %dx%d\n", chars, fontboundingbox_width,
	   fontboundingbox_height);
#endif
	if (flag == 2) {
		fprintf(out, "chars = %d;\n", chars);
		fprintf(out, "fontboundingbox_width = %d;\n", fontboundingbox_width);
		fprintf(out, "fontboundingbox_height = %d;\n", fontboundingbox_height);
		fprintf(out, "fontboundingbox_xoff = %d;\n", fontboundingbox_xoff);
		fprintf(out, "fontboundingbox_yoff = %d;\n", fontboundingbox_yoff);
	}
	//
	//	Some checks.
	//
	if (fontboundingbox_width <= 0 || fontboundingbox_height <= 0) {
	fprintf(stderr, "Need to know the character size\n");
	exit(-1);
	}
	if (chars <= 0) {
	fprintf(stderr, "Need to know the number of characters\n");
	exit(-1);
	}
	if (Outline) {			// Reserve space for outline border
	fontboundingbox_width++;
	fontboundingbox_height++;
	}
	//
	//	Allocate tables
	//
	width_table = malloc(chars * sizeof(*width_table));
	if (!width_table) {
	fprintf(stderr, "Out of memory\n");
	exit(-1);
	}
	encoding_table = malloc(chars * sizeof(*encoding_table));
	if (!encoding_table) {
	fprintf(stderr, "Out of memory\n");
	exit(-1);
	}
	/*	FIXME: needed for proportional fonts.
	   offset_table = malloc(chars * sizeof(*offset_table));
	   if (!offset_table) {
	   fprintf(stderr, "Out of memory\n");
	   exit(-1);
	   }
	 */
	size_t bitmap_size = ((fontboundingbox_width + 7) / 8) * fontboundingbox_height;
	bitmap = malloc(bitmap_size);
	//malloc(((fontboundingbox_width + 7) / 8) * fontboundingbox_height);
	if (!bitmap) {
	fprintf(stderr, "Out of memory\n");
	exit(-1);
	}

	if (flag == 1) Header(out, name, fontboundingbox_width, fontboundingbox_height);

	scanline = -1;
	n = 0;
	encoding = -1;
	bbx = 0;
	bby = 0;
	bbw = 0;
	bbh = 0;
	width = INT_MIN;
	strcpy(charname, "unknown character");
	for (;;) {
	if (!fgets(linebuf, sizeof(linebuf), bdf)) {	// EOF
		break;
	}
	if (!(s = strtok(linebuf, " \t\n\r"))) {	// empty line
		break;
	}
	// printf("token:%s\n", s);
	if (!strcasecmp(s, "STARTCHAR")) {
		p = strtok(NULL, " \t\n\r");
		strcpy(charname, p);
	} else if (!strcasecmp(s, "ENCODING")) {
		p = strtok(NULL, " \t\n\r");
		encoding = atoi(p);
	} else if (!strcasecmp(s, "DWIDTH")) {
		p = strtok(NULL, " \t\n\r");
		width = atoi(p);
	} else if (!strcasecmp(s, "BBX")) {
		p = strtok(NULL, " \t\n\r");
		bbw = atoi(p);
		p = strtok(NULL, " \t\n\r");
		bbh = atoi(p);
		p = strtok(NULL, " \t\n\r");
		bbx = atoi(p);
		p = strtok(NULL, " \t\n\r");
		bby = atoi(p);
	} else if (!strcasecmp(s, "BITMAP")) {
		if (encoding >= 0 && encoding < 256) {
		_width = width - fontboundingbox_xoff;
#if 0
		fprintf(out, "// %3d $%02x '%s'\n", encoding, encoding, charname);
		fprintf(out, "//\twidth %d, bbx %d, bby %d, bbw %d, bbh %d\n",
		width, bbx, bby, bbw, bbh);
#endif
		if (n == chars) {
			fprintf(stderr, "Too many bitmaps for characters\n");
			exit(-1);
		}
		if (width == INT_MIN) {
			fprintf(stderr, "character width not specified\n");
		exit(-1);
		}
		//
		//	Adjust width based on bounding box
		//
		//if (bbx < 0) {
		if (bbx != 0) {
			width += bbx;
			//bbx = 0;
		}
		if (bbx + bbw > width) {
			width = bbx + bbw;
		}
		if (Outline) {		// Reserve space for outline border
			++width;
		}

		if (fontboundingbox_xoff > 0) {
			_width = width - fontboundingbox_xoff;
			_bbx = bbx - fontboundingbox_xoff;
		} else if (fontboundingbox_xoff < 0) {
			_width = width + abs(fontboundingbox_xoff);
			_bbx = bbx + abs(fontboundingbox_xoff);
		}
		if (flag == 1) {
			fprintf(out, "// '%s'\n", charname);
			fprintf(out, "%3d,%d,%d,%d,%d,%d,", encoding, _width, bbw, bbh, bbx, bby);
		} else {
			fprintf(out, "// width=%d fontboundingbox_xoff=%d\n", width, fontboundingbox_xoff);
			fprintf(out, "// bbx=%d _bbx=%d\n", bbx, _bbx);
			fprintf(out, "encoding=%3d charname='%s' width=%d bbw=%d bbh=%d bbx=%d bby=%d\n",
				encoding, charname, _width, bbw, bbh, bbx, bby);
		}

		width_table[n] = width;
		encoding_table[n] = encoding;
		++n;
		if (Outline) {		// Leave first row empty
		scanline = 1;
		} else {
		scanline = 0;
		}
		memset(bitmap, 0, bitmap_size);
		}
	} else if (!strcasecmp(s, "ENDCHAR")) {
		if (encoding >= 0 && encoding < 256) {
		if (_bbx) {
			//dump("Befor RotateBitmap", bitmap, bitmap_size);
			RotateBitmap(bitmap, _bbx, fontboundingbox_width,
				fontboundingbox_height);
			//dump("After RotateBitmap", bitmap, bitmap_size);
		}
		if (Outline) {
			RotateBitmap(bitmap, 1, fontboundingbox_width,
				fontboundingbox_height);
			OutlineCharacter(bitmap, fontboundingbox_width,
				fontboundingbox_height);
		}
		DumpCharacter(out, bitmap, fontboundingbox_width,
		fontboundingbox_height, fontboundingbox_yoff, bbh, bby, flag);
		}
		scanline = -1;
		width = INT_MIN;
	} else if (!strcasecmp(s, "ENDFONT")) {
		if (flag == 1) {
			Last(out);
			fprintf(out, "};\n");
		}
	} else {
		if (scanline >= 0) {
		p = s;
		j = 0;
		while (*p) {
			i = Hex2Int(p);
			++p;
			if (*p) {
			i = Hex2Int(p) | i * 16;
			} else {
			bitmap[j + scanline * ((fontboundingbox_width +
					7) / 8)] = i;
			break;
			}
			/* printf("%d = %d\n",
			   j + scanline * ((fontboundingbox_width + 7)/8), i); */
			bitmap[j + scanline * ((fontboundingbox_width + 7) / 8)] =
			i;
			++j;
			++p;
		}
		++scanline;
		}
	}
	}

	// Output width table for proportional font.
#if 0
	if(!SmartMatrix)
		WidthTable(out, name, width_table, chars);
#endif
	// FIXME: Output offset table for proportional font.
	// OffsetTable(out, name, offset_table, chars);
	// Output encoding table for utf-8 support
#if 0
	EncodingTable(out, name, encoding_table, chars);
	Footer(out, name, fontboundingbox_width, fontboundingbox_height, chars);
#endif
}

//////////////////////////////////////////////////////////////////////////////

///
///	Print version
///
void PrintVersion(void)
{
	printf("bdf2c Version %s, (c) 2009, 2010 by Lutz Sammer\n"
	"\tLicense AGPLv3: GNU Affero General Public License version 3\n",
	VERSION);
}

///
///	Print usage
///
void PrintUsage(void)
{
	printf("Usage: bdf2c [OPTIONs]\n"
	"\t-h or -?\tPrints this short page on stdout\n"
	"\t-b\tRead bdf file from stdin, write to stdout\n"
	"\t-c\tCreate font header on stdout\n"
	"\t-C file\tCreate font header file\n"
	"\t-n name\tName of c font variable (place it before -b)\n"
	"\t-O\tCreate outline for the font.\n");
	printf("\n\tOnly idiots print usage on stderr\n");
}

///
///	Main test program for bdf2c.
///
///
///	@param argc	number of arguments
///	@param argv	arguments vector
///
int main(int argc, char *const argv[])
{
	const char *name;

	name = "font";			// default variable name
	//
	//	Parse arguments.
	//
	for (;;) {
	switch (getopt(argc, argv, "bBcC:n:hOs?-")) {
		case 'b':			// bdf file name
		ReadBdf(stdin, stdout, name, 1);
		continue;
		case 'B':			// bdf file name
		ReadBdf(stdin, stdout, name, 2);
		continue;
		case 'c':			// create header file
		CreateFontHeaderFile(stdout);
		break;
		case 'C':			// create header file
		{
		FILE *out;

		if (!(out = fopen(optarg, "w"))) {
			fprintf(stderr, "Can't open file '%s': %s\n", optarg,
			strerror(errno));
			exit(-1);
		}
		CreateFontHeaderFile(out);
		fclose(out);
		}
		continue;
		case 'n':
		name = optarg;
		continue;
		case 'O':
		Outline = 1;
		continue;
		case 's':
		SmartMatrix = 1;
		continue;

		case EOF:
		break;
		case '?':
		case 'h':			// help usage
		PrintVersion();
		PrintUsage();
		exit(0);
		case '-':
		fprintf(stderr, "We need no long options\n");
		PrintUsage();
		exit(-1);
		case ':':
		PrintVersion();
		fprintf(stderr, "Missing argument for option '%c'\n", optopt);
		exit(-1);
		default:
		PrintVersion();
		fprintf(stderr, "Unkown option '%c'\n", optopt);
		exit(-1);
	}
	break;
	}
	while (optind < argc) {
	fprintf(stderr, "Unhandled argument '%s'\n", argv[optind++]);
	}

	return 0;
}
